package service

import (
	"encoding/json"
	"errors"
	"log"
	"src/config"
	connection2 "src/connection"
	global2 "src/global"
	"src/mapper"
	"src/model"
	"src/utils"
)

type Auth struct {
	userinfo *mapper.User
	userCons []string
}

var AuthI *Auth

// token鉴定逻辑
func (this *Auth) MysqlTokenAuth(token string) (*mapper.User, error) {
	//mysql := utils.NewMysqlClient("x", nil)
	var userinfo mapper.User
	db := utils.NewDbClient("db", nil)
	//sqlStr := "SELECT userid as uid,name as nickname,avatar from user WHERE token = ?"
	//row := mysql.Client.QueryRow(sqlStr, token)
	loginAuthType := config.V().GetString("client.login-auth-type")
	sql_2_1 := config.V().GetString("client." + loginAuthType + ".auth-sql")
	if sql_2_1 == "" {
		demosql := "select userid as uid, avatar ,name as nickname,phone as username from `user` where token=?"
		log.Println("配置文件未配置数据库登录授权节点, 节点位置:%v\n", "client."+loginAuthType+".auth-sql"+";参考值+"+demosql)
		return nil, errors.New("配置文件未配置数据库登录授权节点")
	}
	has, err := db.Client.SQL(sql_2_1, token).Get(&userinfo)

	//然后使用Scan()方法给对应类型变量赋值，以便取出结果,注意传入的是指针
	//err := row.Scan(&userinfo.Uid, &userinfo.Nickname, &userinfo.Avatar)
	if err != nil {
		log.Println("获取mysql用户数据错误, err:%v\n", err)
		return nil, err
	}
	if has {
		return &userinfo, nil
	}
	return nil, errors.New("token验证失败")
}

// token鉴定逻辑
func (this *Auth) RedisTokenAuth(token string) (*mapper.User, error) {

	redis_c := utils.NewRedisClient("name", nil).Client
	//redistokenprefix := config.V().GetString("client.redis-token-prefix")
	redistokenprefix := global2.Constant().RedisTokenPrefix
	s := redis_c.Get(redistokenprefix + token).Val()

	if s == "" {
		return nil, errors.New("授权不存在")
	}
	var userinfo mapper.User
	err := json.Unmarshal([]byte(s), &userinfo)
	if err != nil {
		return nil, err
	}
	if userinfo.Uid == "" {
		return nil, errors.New("用户信息不存在")
	}
	//fmt.Println(reg)
	return &userinfo, nil
}
func (this *Auth) Auth(token string) (*mapper.User, error) {
	loginAuthType := config.V().GetString("client.login-auth-type")
	if loginAuthType == "jwt" {
		return this.JwtAuth(token)
	} else if loginAuthType == "mysql" {
		return this.MysqlTokenAuth(token)
	} else {
		return this.RedisTokenAuth(token)
	}
}

// jwt 鉴权逻辑
func (this *Auth) JwtAuth(token string) (*mapper.User, error) {
	var userinfo mapper.User
	//解析token
	ret, err := utils.JwtParseToken(token)
	if err != nil {
		log.Println(err)
		return nil, errors.New("授权失败" + err.Error())
	}

	//fmt.Printf("userinfo:%v,%v,%v,%v,%v\n", ret.Uid, ret.Scope, ret.UName, ret.ExpiresAt, ret.IssuedAt)
	userinfo.Nickname = ret.UName
	userinfo.Uid = ret.Uid
	this.userinfo = &userinfo
	return &userinfo, nil
}

// 绑定房间鉴权逻辑
func (this *Auth) RoomBindAuthTcp(roomBind *model.RoomBindModel, conn *connection2.Tcp) (*mapper.User, error) {
	var userinfo mapper.User
	//解析token
	if conn.Uid != "" {
		room := global2.Ws_.GetRoomListVal(roomBind.RoomNo)
		//房间不存在，创建房间
		if room == nil {
			//a:=make(map[string]model.RoomBindModel)
			room = make(map[string]string)
			room[conn.Id] = conn.Uid
			//绑定房间用户数据
			global2.Ws_.UpdateRoomList(roomBind.RoomNo, room)
		} else {
			//绑定房间 用户数据
			room[conn.Id] = conn.Uid
			//绑定房间用户数据
			global2.Ws_.UpdateRoomList(roomBind.RoomNo, room)
		}
		conn.RoomNo = roomBind.RoomNo
		return &userinfo, nil
	}
	return nil, errors.New("用户未登录")
}

// 刪除之前綁定过的房间
func (this *Auth) DelOldRoomBind(uid string, oldRoomNo string) {
	roomO := global2.Ws_.GetRoomListVal(oldRoomNo)
	if oldRoomNo != "" && roomO != nil {

		for cid, uid2 := range roomO {
			if uid2 == uid {
				global2.Ws_.DelRoomList(oldRoomNo, cid)
			}
		}
	}
}

// 绑定房间鉴权逻辑
func (this *Auth) RoomBindAuthWs(roomBind *model.RoomBindModel, conn *connection2.Ws) (*mapper.User, error) {
	var userinfo mapper.User
	// 之前绑定过的房间号如果没退出房间 是存在的
	var oldRoomNo = conn.RoomNo
	//解析token
	if conn.Uid != "" {
		this.DelOldRoomBind(conn.Uid, oldRoomNo)
		room := global2.Ws_.GetRoomListVal(roomBind.RoomNo)
		//房间不存在，创建房间
		if room == nil {
			//a:=make(map[string]model.RoomBindModel)
			room = make(map[string]string)
			room[conn.Id] = conn.Uid
			//绑定房间用户数据
			global2.Ws_.UpdateRoomList(roomBind.RoomNo, room)
		} else {
			//绑定房间 用户数据
			room[conn.Id] = conn.Uid
			//绑定房间用户数据
			global2.Ws_.UpdateRoomList(roomBind.RoomNo, room)
		}
		//userinfo.Nickname=
		conn.RoomNo = roomBind.RoomNo

		return &userinfo, nil
	} else {
		return nil, errors.New("未登录")
	}
}

// 检查这个设备id是否已经在线,返回在线的设备链接
func (this *Auth) CheckUidDid(uid string, did string) (*connection2.Ws, error) {
	//var userinfo mapper.User
	usercons := global2.Ws_.GetUserListVal(uid)
	this.userCons = usercons
	if usercons != nil && len(usercons) > 0 {
		for _, connid := range usercons {
			ws := global2.Ws_.GetConnListVal(connid)

			if did == ws.Did {
				return ws, errors.New("已存在终端设备")
			}
		}
	}
	return nil, nil
}

// 检查这个设备id是否已经在线,返回在线的设备链接
func (this *Auth) CheckUid(uid string) (*connection2.Ws, error) {
	//var userinfo mapper.User
	usercons := global2.Ws_.GetUserListVal(uid)
	this.userCons = usercons
	if usercons != nil && len(usercons) > 0 {
		for _, connid := range usercons {
			ws := global2.Ws_.GetConnListVal(connid)
			return ws, errors.New("已存在终端设备")
		}
	}
	return nil, nil
}

//// REDIS 鉴定逻辑
//func Auth(token string) (*mapper.User, error) {
//
//	redisc := utils.NewRedisClient("name", nil).Client
//	s := redisc.Get(global.Constant().RedisTokenPrefix + token).Val()
//	if s == "" {
//		return nil, errors.New("授权不存在")
//	}
//	var userinfo mapper.User
//	json.Unmarshal([]byte(s), &userinfo)
//	if userinfo.Uid == "" {
//		return nil, errors.New("用户信息不存在")
//	}
//	//fmt.Println(reg)
//	return &userinfo, nil
//}
